#ifndef _EXT_BLOCK_MIX_LOG_H_
#define _EXT_BLOCK_MIX_LOG_H_

#include <stdint.h>
#include "rtctime.h"
#include "log_buff_mix.h"

#ifdef __cplusplus
extern "C"
{
#endif

#ifndef FLASH_BLOCK_ERR_NONE
#define FLASH_BLOCK_ERR_NONE 0
#define FLASH_BLOCK_ERR_PAGE_SIZE 1	 
#define FLASH_BLOCK_ERR_BLOCK_SIZE 2 
#define FLASH_BLOCK_ERR_BLOCK_NUMS 3
#define FLASH_BLOCK_ERR_SIZE 4		  
#define FLASH_BLOCK_ERR_PAG_PER_BLK 5 
#define FLASH_BLOCK_ERR_LOG_SIZE 6	  
#endif

	typedef struct
	{
		uint32_t block_next;  
		uint32_t block_start; 
		uint8_t Err;		  
		uint8_t Checked;	  
		uint16_t save_cnt;	  
	} block_mix_log_info_type;

	typedef struct
	{
		uint16_t (*init)(void);
		uint16_t (*save)(void);
		int32_t (*read)(mix_log_obj_type *log_obj);
		void (*clr)(void);
		int32_t (*time_search)(uint32_t time, int8_t mode, mix_log_obj_type *site);
		int32_t (*site_move)(mix_log_obj_type *site, int32_t inc);
		int32_t (*get_next_site)(mix_log_obj_type *site);

		int32_t (*site_iter)(
			mix_log_obj_type *s_s, mix_log_obj_type *s_e,
			int32_t (*iter_back)(mix_log_obj_type *log_obj));

		int32_t (*time_iter)(
			uint32_t tim_start, uint32_t tim_end,
			int32_t (*iter_back)(mix_log_obj_type *log_obj));

		uint16_t (*buf_init)(void);
		uint16_t (*buf_save)(uint32_t tim, void *dat, uint16_t len);
		uint16_t (*buf_read)(mix_log_obj_type *log_obj);
		uint16_t (*buf_modify)(mix_log_obj_type *log_site, ii16 offset, void *dat, ii16 len);
	} block_mix_log_api_type;

	typedef struct
	{
		uint32_t block_base;									  
		uint16_t block_amount;									  
		block_mix_log_info_type *Info;							  
		const mix_log_buff_cfg_type buf_cfg;					  
		void (*erase)(uint32_t block_addr);						  
		void (*program)(uint32_t block_addr);					  
		void (*read)(uint32_t Addr, uint16_t Len, uint8_t *Data); 
		const block_mix_log_api_type *api;
	} block_mix_log_cfg_type;

	uint16_t mix_log_buff_init(const block_mix_log_cfg_type *cfg);
	uint16_t mix_log_buff_save(const block_mix_log_cfg_type *cfg, uint32_t tim, void *dat, uint16_t len);
	uint16_t mix_log_buff_read(const block_mix_log_cfg_type *cfg, mix_log_obj_type *log_obj);
	uint16_t mix_log_buff_modify(const block_mix_log_cfg_type *cfg, mix_log_obj_type *log_site, ii16 offset, void *dat, ii16 len);

	uint16_t block_mix_log_check(const block_mix_log_cfg_type *Cfg);

	uint16_t block_mix_log_save(const block_mix_log_cfg_type *Cfg);

	int32_t block_mix_log_read(const block_mix_log_cfg_type *cfg, mix_log_obj_type *log_obj);

	void block_mix_log_clr(const block_mix_log_cfg_type *cfg);

	int32_t block_mix_log_time_search(const block_mix_log_cfg_type *Cfg, uint32_t time, int8_t mode, mix_log_obj_type *site);

	int32_t block_mix_log_site_move(const block_mix_log_cfg_type *cfg, mix_log_obj_type *site, int32_t inc);

	int32_t block_mix_log_get_next_site(const block_mix_log_cfg_type *cfg, mix_log_obj_type *site);

	int32_t block_mix_log_site_iter(
		const block_mix_log_cfg_type *cfg,
		mix_log_obj_type *s_s, mix_log_obj_type *s_e,
		int32_t (*iter_back)(mix_log_obj_type *log_obj));

	int32_t block_mix_log_time_iter(
		const block_mix_log_cfg_type *cfg,
		uint32_t tim_start, uint32_t tim_end,
		int32_t (*iter_back)(mix_log_obj_type *log_obj));

#define block_mix_log_api_make(obj)                                                                 \
                                                                                                    \
	static uint16_t obj##_init(void);                                                               \
	static uint16_t obj##_save(void);                                                               \
	static int32_t obj##_read(mix_log_obj_type *log_obj);                                           \
	static void obj##_clr(void);                                                                    \
	static int32_t obj##_time_search(uint32_t time, int8_t mode, mix_log_obj_type *site);           \
	static int32_t obj##_site_move(mix_log_obj_type *site, int32_t inc);                            \
	static int32_t obj##_get_next_site(mix_log_obj_type *site);                                     \
	static int32_t obj##_site_iter(                                                                 \
		mix_log_obj_type *s_s, mix_log_obj_type *s_e,                                               \
		int32_t (*iter_back)(mix_log_obj_type * log_obj));                                          \
	static int32_t obj##_time_iter(                                                                 \
		uint32_t tim_start, uint32_t tim_end,                                                       \
		int32_t (*iter_back)(mix_log_obj_type * log_obj));                                          \
                                                                                                    \
	static uint16_t obj##_buf_init(void);                                                           \
	static uint16_t obj##_buf_save(uint32_t tim, void *dat, uint16_t len);                          \
	static uint16_t obj##_buf_read(mix_log_obj_type *log_obj);                                      \
	static uint16_t obj##_buf_modify(mix_log_obj_type *log_site, ii16 offset, void *dat, ii16 len); \
                                                                                                    \
	uint16_t obj##_init(void)                                                                       \
	{                                                                                               \
		return block_mix_log_check(&obj);                                                           \
	}                                                                                               \
	uint16_t obj##_save(void)                                                                       \
	{                                                                                               \
		return block_mix_log_save(&obj);                                                            \
	}                                                                                               \
	int32_t obj##_read(mix_log_obj_type *log_obj)                                                   \
	{                                                                                               \
		return block_mix_log_read(&obj, log_obj);                                                   \
	}                                                                                               \
	void obj##_clr(void)                                                                            \
	{                                                                                               \
		block_mix_log_clr(&obj);                                                                    \
	}                                                                                               \
	int32_t obj##_time_search(uint32_t time, int8_t mode, mix_log_obj_type *site)                   \
	{                                                                                               \
		return block_mix_log_time_search(&obj, time, mode, site);                                   \
	}                                                                                               \
	int32_t obj##_site_move(mix_log_obj_type *site, int32_t inc)                                    \
	{                                                                                               \
		return block_mix_log_site_move(&obj, site, inc);                                            \
	}                                                                                               \
	static int32_t obj##_get_next_site(mix_log_obj_type *site)                                      \
	{                                                                                               \
		return block_mix_log_get_next_site(&obj, site);                                             \
	}                                                                                               \
	static int32_t obj##_site_iter(                                                                 \
		mix_log_obj_type *s_s, mix_log_obj_type *s_e,                                               \
		int32_t (*iter_back)(mix_log_obj_type * log_obj))                                           \
	{                                                                                               \
		return block_mix_log_site_iter(&obj, s_s, s_e, iter_back);                                  \
	}                                                                                               \
	static int32_t obj##_time_iter(                                                                 \
		uint32_t tim_start, uint32_t tim_end,                                                       \
		int32_t (*iter_back)(mix_log_obj_type * log_obj))                                           \
	{                                                                                               \
		return block_mix_log_time_iter(&obj, tim_start, tim_end, iter_back);                        \
	}                                                                                               \
	static uint16_t obj##_buf_init(void)                                                            \
	{                                                                                               \
		return mix_log_buff_init(&obj);                                                             \
	}                                                                                               \
	static uint16_t obj##_buf_save(uint32_t tim, void *dat, uint16_t len)                           \
	{                                                                                               \
		return mix_log_buff_save(&obj, tim, dat, len);                                              \
	}                                                                                               \
	static uint16_t obj##_buf_read(mix_log_obj_type *log_obj)                                       \
	{                                                                                               \
		return mix_log_buff_read(&obj, log_obj);                                                    \
	}                                                                                               \
	static uint16_t obj##_buf_modify(mix_log_obj_type *log_site, ii16 offset, void *dat, ii16 len)  \
	{                                                                                               \
		return mix_log_buff_modify(&obj, log_site, offset, dat, len);                               \
	}                                                                                               \
	const block_mix_log_api_type obj##_api = {                                                      \
		obj##_init,                                                                                 \
		obj##_save,                                                                                 \
		obj##_read,                                                                                 \
		obj##_clr,                                                                                  \
		obj##_time_search,                                                                          \
		obj##_site_move,                                                                            \
		obj##_get_next_site,                                                                        \
		obj##_site_iter,                                                                            \
		obj##_time_iter,                                                                            \
		obj##_buf_init,                                                                             \
		obj##_buf_save,                                                                             \
		obj##_buf_read,                                                                             \
		obj##_buf_modify}

#define block_mix_log_api_ref(obj) extern const block_mix_log_api_type obj##_api
#define block_mix_log_api_name(obj) &obj##_api

#ifdef __cplusplus
}
#endif

#endif
